package com.ruoyi.common.utils;

import org.apache.poi.ss.usermodel.Cell;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class CommonUtil {
    private static final int  BUFFER_SIZE = 2 * 1024;
    /**
     * 压缩成ZIP
     * @param sourceFile 压缩文件夹路径
     * @param out    压缩文件输出流
     * @param KeepDirStructure  是否保留原来的目录结构,true:保留目录结构;
     *                          false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(File sourceFile, OutputStream out, boolean KeepDirStructure)
            throws RuntimeException{
        ZipOutputStream zos = null ;
        try {
            zos = new ZipOutputStream(out);
            compress(sourceFile,zos,sourceFile.getName(),KeepDirStructure);
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils",e);
        }finally{
            if(zos != null){
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 递归压缩方法
     * @param sourceFile 源文件
     * @param zos        zip输出流
     * @param name       压缩后的名称
     * @param KeepDirStructure  是否保留原来的目录结构,true:保留目录结构;
     *                          false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws Exception
     */
    private static void compress(File sourceFile, ZipOutputStream zos, String name,
                                 boolean KeepDirStructure) throws Exception{
        byte[] buf = new byte[BUFFER_SIZE];
        if(sourceFile.isFile()){
            // 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
            zos.putNextEntry(new ZipEntry(name));
            // copy文件到zip输出流中
            int len;
            FileInputStream in = new FileInputStream(sourceFile);
            while ((len = in.read(buf)) != -1){
                zos.write(buf, 0, len);
            }
            // Complete the entry
            zos.closeEntry();
            in.close();
        } else {
            File[] listFiles = sourceFile.listFiles();
            if(listFiles == null || listFiles.length == 0){
                // 需要保留原来的文件结构时,需要对空文件夹进行处理
                if(KeepDirStructure){
                    // 空文件夹的处理
                    zos.putNextEntry(new ZipEntry(name + "/"));
                    // 没有文件，不需要文件的copy
                    zos.closeEntry();
                }
            }else {
                for (File file : listFiles) {
                    // 判断是否需要保留原来的文件结构
                    if (KeepDirStructure) {
                        // 注意：file.getName()前面需要带上父文件夹的名字加一斜杠,
                        // 不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
                        compress(file, zos, name + "/" + file.getName(),KeepDirStructure);
                    } else {
                        compress(file, zos, file.getName(),KeepDirStructure);
                    }
                }
            }
        }
    }


    /**
     * 删除文件夹及其子目录
     * @param fileName 文件路径
     * @param isForceDelete 是否强制删除有子文件夹的目录
     */
    public static void deleteFile(String fileName,boolean isForceDelete){
        File file = new File(fileName);
        if(file.exists()){
            file.delete();
        }
        if(file.exists()){
            if(!isForceDelete){
                return;
            }
            String[] paths = file.list();
            for(String str:paths){
                deleteFile(fileName+"/"+str,isForceDelete);
            }
            file.delete();
            paths = null;	// lets gc do its works
        }
        file = null;	// lets gc do its works
    }

    /**
     * 获取单元格数据
     * @param cell
     * @return
     */
    public static String getCellValue(Cell cell) {
        if (null != cell) {
            switch (cell.getCellTypeEnum()) {
                case NUMERIC: // 数字
                    String val = null;
                    try {
                        if (isInteger(cell.getNumericCellValue())) {
                            DecimalFormat df = new DecimalFormat("0");//处理科学计数法
                            val = df.format(cell.getNumericCellValue());
                        } else {
                            val = Double.valueOf(cell.getNumericCellValue()).toString();
                        }
                    } catch (Exception e) {
                        DecimalFormat df = new DecimalFormat("0");//处理科学计数法
                        val = df.format(cell.getNumericCellValue());
                    }
                    return val;
                case STRING: // 字符串
                    return cell.getStringCellValue() + "";
                case BOOLEAN: // Boolean
                    return cell.getBooleanCellValue() + "";
                case FORMULA: // 公式
                    return cell.getCellFormula() + "   ";
                case BLANK: // 空值
                    return "";
                case ERROR: // 故障
                    return "";
                default:
                    return "未知类型   ";
            }
        } else {
            return "";
        }
    }

    /**
     * 判断是否是整数
     * @param d
     * @return
     */
    public static boolean isInteger(double d) {
        double eps = 1e-10;
        boolean isInteger = d-Math.floor(d) < eps;
        return isInteger;
    }
    /**
     * 判断是否是整数
     * @param str
     * @return
     */
    public static boolean isInteger(String str) {
        if (str==null||str.equals("")){
            return false;
        }
        Pattern pattern = Pattern.compile("^[0-9]+$");
        return pattern.matcher(str).matches();
    }
    /**
     * 判断是否是数字类型
     * @param str
     * @return 如果为空返回false  匹配返回true
     */
    public static boolean checkNumber(String str) {
        if (str==null||str.equals("")){
            return false;
        }
        Pattern pattern = Pattern.compile("[+-]?[0-9]+(\\.[0-9]+)?");
        return pattern.matcher(str).matches();
    }

    /**
     * 字符串是否包含中文
     *
     * @param str 待校验字符串
     * @return true 包含中文字符  false 不包含中文字符
     */
    public static boolean isContainChinese(String str) {
        if (StringUtils.isEmpty(str)) {
            return false;
        }
        Pattern p = Pattern.compile("[\u4E00-\u9FA5|\\！|\\，|\\。|\\（|\\）|\\《|\\》|\\“|\\”|\\？|\\：|\\；|\\【|\\】]");
        Matcher m = p.matcher(str);
        if (m.find()) {
            return true;
        }
        return false;
    }
}
